<template>
  <div style="position: relative">
    <div v-if="!loading && !error">
      <div class="verify-img-out">
        <div class="verify-img-panel" :style="{
          width: setSize.imgWidth,
          height: setSize.imgHeight,
          'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
          'margin-bottom': vSpace + 'px',
        }">
          <div class="verify-refresh" style="z-index: 3" @click="refresh" v-show="showRefresh">
            <i class="captcha-icon-refresh"></i>
          </div>
          <img :src="'data:image/png;base64,' + pointBackImgBase" ref="canvas" alt=""
            style="width: 100%; height: 100%; display: block" @click="bindingClick ? canvasClick($event) : undefined" />

          <div v-for="(tempPoint, index) in tempPoints" :key="index" class="point-area" :style="{
            'background-color': '#1abd6c',
            color: '#fff',
            'z-index': 9999,
            width: '20px',
            height: '20px',
            'text-align': 'center',
            'line-height': '20px',
            'border-radius': '50%',
            position: 'absolute',
            top: parseInt(tempPoint.y - 10) + 'px',
            left: parseInt(tempPoint.x - 10) + 'px',
          }">
            {{ index + 1 }}
          </div>
        </div>
      </div>
      <!-- 'height': this.barSize.height, -->
      <div class="verify-bar-area" :style="{
        width: setSize.imgWidth,
        color: this.barAreaColor,
        'border-color': this.barAreaBorderColor,
        'line-height': this.barSize.height,
      }">
        <span class="verify-msg">{{ text }}</span>
      </div>
    </div>
    <div v-else-if="!error">
      <div style="text-align: center">
        <i class="captcha-icon-refresh captcha-spin" style="opacity:.85"></i>
        <div style="color:#999; margin-top: 10px; font-size: 14px;">加载中...</div>
      </div>
    </div>
    <div v-else>
      <div style="text-align: center">
        <div style="font-size:14px; color:#f30; margin: 20px auto;">数据获取错误：无法获取安全验证信息</div>
        <a href="javascript:void(0)" @click="refresh">点击重新获取</a>
      </div>
    </div>

  </div>
</template>
<script>
/* eslint-disable*/
/**
 * VerifyPoints
 * @description 点选
 * */
import {
  resetSize,
  _code_chars,
  _code_color1,
  _code_color2,
  request
} from "../utils/util.js";
import { aesEncrypt } from "../utils/ase.js";
export default {
  name: "VerifyPoints",
  props: {
    //弹出式pop，固定fixed
    mode: {
      type: String,
      default: "fixed",
    },
    captchaType: {
      type: String,
    },
    //间隔
    vSpace: {
      type: Number,
      default: 5,
    },
    imgSize: {
      type: Object,
      default() {
        return {
          width: "310px",
          height: "155px",
        };
      },
    },
    barSize: {
      type: Object,
      default() {
        return {
          width: "310px",
          height: "40px",
        };
      },
    },
    captchaGetUrl: {
      type: [String, Function],
      default: '/captcha/get'
    },
    captchaCheckUrl: {
      type: [String, Function],
      default: '/captcha/check'
    },
    params: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      secretKey: "", //后端返回的ase加密秘钥
      checkNum: 3, //默认需要点击的字数
      fontPos: [], //选中的坐标信息
      checkPosArr: [], //用户点击的坐标
      num: 1, //点击的记数
      pointBackImgBase: "", //后端获取到的背景图片
      poinTextList: [], //后端返回的点击字体顺序
      backToken: "", //后端返回的token值
      setSize: {
        imgHeight: 0,
        imgWidth: 0,
        barHeight: 0,
        barWidth: 0,
      },
      tempPoints: [],
      text: "",
      barAreaColor: undefined,
      barAreaBorderColor: undefined,
      showRefresh: true,
      bindingClick: true,
      canvas: null,
      loading: true,
      error: null,
    };
  },
  mounted() {
    this.$el.onselectstart = function () {
      return false;
    };
    this.init();
  },

  methods: {
    responseFormat(success, data, error = '请求失败') {
      return {
        repCode: !!success ? '0000' : '6111',
        repData: data,
        repMsg: error
      }
    },

    async init() {
      //加载页面
      this.fontPos.splice(0, this.fontPos.length);
      this.checkPosArr.splice(0, this.checkPosArr.length);
      this.num = 1;
      await this.getPictrue();
      this.$nextTick(() => {
        let { imgHeight, imgWidth, barHeight, barWidth } = resetSize(this);
        this.setSize = {
          imgHeight,
          imgWidth,
          barHeight,
          barWidth,
        };
        this.$parent.$emit("ready", this);
      });
    },

    canvasClick(e) {
      const { canvas } = this;
      this.checkPosArr.push(this.getMousePos(canvas, e));

      if (this.num == this.checkNum) {
        this.num = this.createPoint(this.getMousePos(canvas, e));
        //按比例转换坐标值
        let arr = this.pointTransfrom(this.checkPosArr, this.setSize);
        this.checkPosArr.length = 0;
        this.checkPosArr.push(...arr);

        //等创建坐标执行完
        setTimeout(async () => {
          // var flag = this.comparePos(this.fontPos, this.checkPosArr);
          //发送后端请求
          var captchaVerification = this.secretKey
            ? aesEncrypt(
              this.backToken + "---" + JSON.stringify(this.checkPosArr),
              this.secretKey
            )
            : this.backToken + "---" + JSON.stringify(this.checkPosArr);
          let data = {
            captchaType: this.captchaType,
            pointJson: this.secretKey
              ? aesEncrypt(JSON.stringify(this.checkPosArr), this.secretKey)
              : JSON.stringify(this.checkPosArr),
            token: this.backToken,
            ...this.params
          };
          let res;
          try {
            if(typeof this.captchaCheckUrl === 'string') {
              res = await request(this.captchaCheckUrl, data)
            } else if(typeof this.captchaCheckUrl === 'function') {
              res = await this.captchaCheckUrl(data, this.responseFormat)
              if(!res.repCode) {
                let errorMsg = 'captchaCheckUrl必须返回{repCode}'
                console.error(errorMsg)
                throw new Error(errorMsg)
              }
            } else {
              let errorMsg = 'captchaCheckUrl不是字符串或者函数'
              console.error(errorMsg)
              throw new Error(errorMsg)
            }

            if (res.repCode == "0000") {
                this.barAreaColor = "#4cae4c";
                this.barAreaBorderColor = "#5cb85c";
                this.text = "验证成功";
                this.bindingClick = false;
                if (this.mode == "pop") {
                  setTimeout(() => {
                    this.$parent.closeBox({ captchaVerification });
                    this.refresh();
                  }, 1500);
                }

                this.$parent.$emit("success", { captchaVerification });
              } else {
                this.$parent.$emit("error", this);
                this.barAreaColor = "#d9534f";
                this.barAreaBorderColor = "#d9534f";
                this.text = "验证失败";
                setTimeout(() => {
                  this.refresh();
                }, 700);
              }

          } catch(e) {
            this.$parent.$emit("error", e);
          } finally {
            // 
          }
        }, 400);
      }
      if (this.num < this.checkNum) {
        this.num = this.createPoint(this.getMousePos(canvas, e));
      }
    },

    getMousePos(obj, e) {
      const { offsetX, offsetY } = e;
      return { x: offsetX, y: offsetY };
    },

    createPoint(pos) {
      this.tempPoints.push(Object.assign({}, pos));
      return this.num + 1;
    },

    async refresh() {
      this.tempPoints.splice(0, this.tempPoints.length);
      this.barAreaColor = "#000";
      this.barAreaBorderColor = "#ddd";
      this.bindingClick = true;
      this.fontPos.splice(0, this.fontPos.length);
      this.checkPosArr.splice(0, this.checkPosArr.length);
      this.num = 1;
      await this.getPictrue();
      this.text = "验证失败";
      this.showRefresh = true;
    },
    async getPictrue() {
      const { captchaType } = this;
      this.loading = true;
      this.error = null

      let res;
      try {
        if (typeof this.captchaGetUrl === 'string') {
          res = await request(this.captchaGetUrl, { captchaType })
        } else if (typeof this.captchaGetUrl === 'function') {
          res = await this.captchaGetUrl({ captchaType }, this.responseFormat)
          if (!res.repCode || !res.repData) {
            let errorMsg = 'captchaGetUrl必须返回{repCode, repData, repMsg?}'
            console.error(errorMsg)
            throw new Error(errorMsg)
          }
        } else {
          let errorMsg = 'captchaGetUrl不是字符串或者函数'
          console.error(errorMsg)
          throw new Error(errorMsg)
        }

        const { repCode, repData, repMsg } = res;
        if (repCode == "0000") {
          const { originalImageBase64, token, secretKey, wordList } = repData;
          this.pointBackImgBase = originalImageBase64;
          this.backToken = token;
          this.secretKey = secretKey;
          this.poinTextList = wordList;
          this.text = "请依次点击【" + wordList.join(",") + "】";
        } else {
          this.text = repMsg;
        }
      } catch (e) {
        this.$parent.$emit("error", e);
      } finally {
        this.loading = false
      }
    },

    pointTransfrom(pointArr, imgSize) {
      const { imgWidth, imgHeight } = imgSize;
      return pointArr.map((p) => {
        const { x, y } = p;
        return {
          x: Math.round((310 * x) / parseInt(imgWidth)),
          y: Math.round((155 * y) / parseInt(imgHeight)),
        };
      });
    },
  },
};
</script>
